/*
  Simple DirectMedia Layer
  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>

  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"

#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <keyboard.h>

#include "SDL.h"
#include "SDL_endian.h"
#include "SDL_scancode.h"
#include "../../events/SDL_events_c.h"
#include "../../events/scancodes_sylixos.h" /* adds sylixos_scancode_table */

#ifdef SDL_INPUT_SYLIXOSKBD
int xkbd_fd;

int
SDL_SYLIXOS_KEYBOARD_Init(void)
{
    if (xkbd_fd <= 0)
        xkbd_fd = open("/dev/input/xkbd", O_RDONLY | O_NONBLOCK);

    if (xkbd_fd > 0) {
        return 0;
    } else {
        return -1;
    }
}

void
SDL_SYLIXOS_KEYBOARD_Quit(void)
{
    close(xkbd_fd);
}

void
SDL_SYLIXOS_KEYBOARD_Poll(void)
{
    int ret;
    int unicode = 0;
    SDL_Scancode sdl_code;
    keyboard_event_notify kbd_event;

    memset(&kbd_event, 0, sizeof(kbd_event));
    ret = read(xkbd_fd, (void *)&kbd_event, sizeof(keyboard_event_notify));
    if (ret <= 0) {
        return;
    }

    unicode = kbd_event.keymsg[0];
    if ((unicode < 0xff) && (unicode > 0)) {
        sdl_code = sylixos_scancode_table[unicode];
    } else {
        switch (unicode) {
        case K_F1:     sdl_code = SDL_SCANCODE_F1;     break;
        case K_F2:     sdl_code = SDL_SCANCODE_F2;     break;
        case K_F3:     sdl_code = SDL_SCANCODE_F3;     break;
        case K_F4:     sdl_code = SDL_SCANCODE_F4;     break;
        case K_F5:     sdl_code = SDL_SCANCODE_F5;     break;
        case K_F6:     sdl_code = SDL_SCANCODE_F6;     break;
        case K_F7:     sdl_code = SDL_SCANCODE_F7;     break;
        case K_F8:     sdl_code = SDL_SCANCODE_F8;     break;
        case K_F9:     sdl_code = SDL_SCANCODE_F9;     break;
        case K_F10:    sdl_code = SDL_SCANCODE_F10;    break;
        case K_F11:    sdl_code = SDL_SCANCODE_F11;    break;
        case K_F12:    sdl_code = SDL_SCANCODE_F12;    break;
        case K_F13:    sdl_code = SDL_SCANCODE_F13;    break;
        case K_F14:    sdl_code = SDL_SCANCODE_F14;    break;
        case K_F15:    sdl_code = SDL_SCANCODE_F15;    break;
        case K_F16:    sdl_code = SDL_SCANCODE_F16;    break;
        case K_F17:    sdl_code = SDL_SCANCODE_F17;    break;
        case K_F18:    sdl_code = SDL_SCANCODE_F18;    break;
        case K_F19:    sdl_code = SDL_SCANCODE_F19;    break;
        case K_F20:    sdl_code = SDL_SCANCODE_F20;    break;

        case K_CAPSLOCK:     sdl_code = SDL_SCANCODE_CAPSLOCK;     break;
        case K_NUMLOCK:      sdl_code = SDL_SCANCODE_NUMLOCKCLEAR; break;

        case K_PRINTSCREEN:  sdl_code = SDL_SCANCODE_PRINTSCREEN;  break;
        case K_SCROLLLOCK:   sdl_code = SDL_SCANCODE_SCROLLLOCK;   break;
        case K_PAUSEBREAK:   sdl_code = SDL_SCANCODE_PAUSE;        break;

        case K_CTRL:         sdl_code = SDL_SCANCODE_LCTRL;        break;
        case K_ALT:          sdl_code = SDL_SCANCODE_LALT;         break;
        case K_SHIFT:        sdl_code = SDL_SCANCODE_LSHIFT;       break;
        case K_CTRLR:        sdl_code = SDL_SCANCODE_RCTRL;        break;
        case K_ALTR:         sdl_code = SDL_SCANCODE_RALT;         break;
        case K_SHIFTR:       sdl_code = SDL_SCANCODE_RSHIFT;       break;

        case K_INSERT:       sdl_code = SDL_SCANCODE_INSERT;       break;
        case K_HOME:         sdl_code = SDL_SCANCODE_HOME;         break;
        case K_DELETE:       sdl_code = SDL_SCANCODE_DELETE;       break;
        case K_END:          sdl_code = SDL_SCANCODE_END;          break;
        case K_PAGEUP:       sdl_code = SDL_SCANCODE_PAGEUP;       break;
        case K_PAGEDOWN:     sdl_code = SDL_SCANCODE_PAGEDOWN;     break;

        case K_UP:           sdl_code = SDL_SCANCODE_UP;           break;
        case K_DOWN:         sdl_code = SDL_SCANCODE_DOWN;         break;
        case K_LEFT:         sdl_code = SDL_SCANCODE_LEFT;         break;
        case K_RIGHT:        sdl_code = SDL_SCANCODE_RIGHT;        break;
        default:             sdl_code = 0;                         break;
        }
    }

    if (sdl_code != SDL_SCANCODE_UNKNOWN) {
        if (kbd_event.type & KE_RELEASE) {
            SDL_SendKeyboardKey(SDL_RELEASED, sdl_code);
        } else if (kbd_event.type & KE_PRESS /* key repeated */) {
            SDL_SendKeyboardKey(SDL_PRESSED, sdl_code);
        }
    }
}
#endif  /* SDL_INPUT_SYLIXOSKBD */
